package ca.ubc.icapture.genapha.actions;

import ca.ubc.icapture.genapha.beans.MakePathwayGeneComparison;
import ca.ubc.icapture.genapha.forms.MakePathwayForm;
import ca.ubc.icapture.genapha.forms.PathwayForm;
import icapture.SQLMgr;
import icapture.beans.DB.Gene;
import icapture.beans.DB.Result;
import icapture.beans.DB.Values;
import icapture.genapha.GenaphaTools;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class MakePathwayAction extends Action
{

    @Override
    public ActionForward execute(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
    {
        ActionForward forward = new ActionForward();
        HttpSession session = request.getSession();
        final MakePathwayForm makePathwayForm = (MakePathwayForm) form;

        if (makePathwayForm.getSubmitType().isEmpty())
        {
            // Populate available genes list
            ArrayList<Gene> genes = new ArrayList<Gene>();
            genes.addAll(SQLMgr.getGenesNotInXChrom());
            makePathwayForm.setAvailableGenes(genes);

            // Send to display
            forward = mapping.findForward("display");
        }
        else if (makePathwayForm.getSubmitType().equalsIgnoreCase("Next"))
        {
            try
            {
                ArrayList<MakePathwayGeneComparison> geneList = new ArrayList<MakePathwayGeneComparison>();

                // Add selected genes to the list
                if (makePathwayForm.getSelectedGenes() != null && makePathwayForm.getSelectedGenes().length > 0)
                {
                    for (String id : makePathwayForm.getSelectedGenes())
                    {
                        Gene gene = SQLMgr.getGene(Integer.parseInt(id));
                        if (gene != null)
                        {
                            MakePathwayGeneComparison pc = new MakePathwayGeneComparison();
                            pc.setGene(gene);
                            pc.setPathwayGeneName(gene.getName());
                            pc.setSnpCount(Integer.toString(SQLMgr.getSNPs(gene).size()));
                            geneList.add(pc);
                        }
                    }
                }

                // Add manually written genes to the list
                if (makePathwayForm.getGenes() != null && !makePathwayForm.getGenes().isEmpty())
                {
                    String[] tmp = makePathwayForm.getGenes().split("\n");
                    for (int i = 0; i < tmp.length; i++)
                    {
                        MakePathwayGeneComparison pc = new MakePathwayGeneComparison();
                        pc.setPathwayGeneName(tmp[i].trim().toUpperCase());
                        Gene gene = SQLMgr.getGene(tmp[i].trim().toUpperCase());
                        if (gene != null)
                        {
                            pc.setGene(gene);
                            pc.setSnpCount(Integer.toString(SQLMgr.getSNPs(gene).size()));
                        }
                        geneList.add(pc);
                    }
                }

                // Process the FormFile
                if (makePathwayForm.getFile() != null)
                {
                    ArrayList<String> fileContents = GenaphaTools.readFile(makePathwayForm.getFile().getInputStream());
                    for (String geneName : fileContents)
                    {
                        MakePathwayGeneComparison pc = new MakePathwayGeneComparison();
                        pc.setPathwayGeneName(geneName.trim().toUpperCase());
                        Gene gene = SQLMgr.getGene(geneName.trim().toUpperCase());
                        if (gene != null)
                        {
                            pc.setGene(gene);
                            pc.setSnpCount(Integer.toString(SQLMgr.getSNPs(gene).size()));
                        }
                        geneList.add(pc);
                    }
                }

                makePathwayForm.setGeneList(geneList);
                forward = mapping.findForward("next");
            }
            catch (Exception e)
            {
                Result result = new Result();
                result.setStatus("Error");
                SQLMgr.updateResult(result);
                e.printStackTrace();

                forward = mapping.findForward("error");
            }
        }
        else
        {
            PathwayForm pathwayForm = new PathwayForm();
            pathwayForm.setPathwayName("Custom Pathway");
            ArrayList<Gene> geneList = new ArrayList<Gene>();
            for (MakePathwayGeneComparison mpgc : makePathwayForm.getGeneList())
            {
                geneList.add(mpgc.getGene());
            }
            pathwayForm.setGeneList(geneList);
            session.setAttribute("pathwayForm", pathwayForm);

            StringBuilder edge = new StringBuilder();
            StringBuilder node = new StringBuilder();

            StringBuilder asthmaJS = new StringBuilder();
            StringBuilder atopyJS = new StringBuilder();
            StringBuilder ahrJS = new StringBuilder();
            StringBuilder atopicAsthmaJS = new StringBuilder();

            ArrayList<Double> asthmaVals = new ArrayList<Double>();
            ArrayList<Double> atopyVals = new ArrayList<Double>();
            ArrayList<Double> ahrVals = new ArrayList<Double>();
            ArrayList<Double> atopicAsthmaVals = new ArrayList<Double>();

            // Make node and edge strings for medusa
            Iterator<MakePathwayGeneComparison> mpgcIter = makePathwayForm.getGeneList().iterator();
            while (mpgcIter.hasNext())
            {
                Gene gene = mpgcIter.next().getGene();
                if (gene != null)
                {
                    edge.append(gene.getName() + " p=0.03:");
                    edge.append(gene.getName() + " p=0.03:2:1:1.0;");

                    node.append(gene.getName() + " p=0.03");
                    node.append(":0.5:0.5: :2:p=0.03;");

                    String pvalue;
                    // Get minimum pvalues for this gene, asthma phenotype, and combined cohort
                    Values value = SQLMgr.getMinPalueValue(gene, 0, 10, 0);
                    if (value == null)
                    {
                        pvalue = "";
                    }
                    else
                    {
                        pvalue = Double.toString(value.getCorrectedPValue());
                        asthmaVals.add(value.getCorrectedPValue());
                    }
                    asthmaJS.append("document.medusa.setNodePValue('" + gene.getName() + "', '" + pvalue + "');\n");

                    // Get minimum pvalues for this gene, atopy phenotype, and combined cohort
                    value = SQLMgr.getMinPalueValue(gene, 1, 10, 0);
                    if (value == null)
                    {
                        pvalue = "";
                    }
                    else
                    {
                        pvalue = Double.toString(value.getCorrectedPValue());
                        atopyVals.add(value.getCorrectedPValue());
                    }
                    atopyJS.append("document.medusa.setNodePValue('" + gene.getName() + "', '" + pvalue + "');\n");

                    // Get minimum pvalues for this gene, atopic asthma phenotype, and combined cohort
                    value = SQLMgr.getMinPalueValue(gene, 11, 10, 0);
                    if (value == null)
                    {
                        pvalue = "";
                    }
                    else
                    {
                        pvalue = Double.toString(value.getCorrectedPValue());
                        atopicAsthmaVals.add(value.getCorrectedPValue());
                    }
                    atopicAsthmaJS.append("document.medusa.setNodePValue('" + gene.getName() + "', '" + pvalue + "');\n");

                    // Get minimum pvalues for this gene, ahr phenotype, and combined cohort
                    value = SQLMgr.getMinPalueValue(gene, 8, 10, 0);
                    if (value == null)
                    {
                        pvalue = "";
                    }
                    else
                    {
                        pvalue = Double.toString(value.getCorrectedPValue());
                        ahrVals.add(value.getCorrectedPValue());
                    }
                    ahrJS.append("document.medusa.setNodePValue('" + gene.getName() + "', '" + pvalue + "');\n");
                }
                else
                {
                    mpgcIter.remove();
                }
            }

            asthmaJS.append("document.getElementById('pathwayScore').innerHTML ='Nyholt Pathway Score: p=" + corrected(asthmaVals) + "';\n");
            atopyJS.append("document.getElementById('pathwayScore').innerHTML ='Nyholt Pathway Score: p=" + corrected(atopyVals) + "';\n");
            atopicAsthmaJS.append("document.getElementById('pathwayScore').innerHTML ='Nyholt Pathway Score: p=" + corrected(atopicAsthmaVals) + "';\n");
            ahrJS.append("document.getElementById('pathwayScore').innerHTML ='Nyholt Pathway Score: p=" + corrected(ahrVals) + "';\n");

            asthmaJS.append("document.getElementById('sidacPathwayScore').innerHTML ='Sidac Pathway Score: p=" + sidacCorrection(asthmaVals) + "';");
            atopyJS.append("document.getElementById('sidacPathwayScore').innerHTML ='Sidac Pathway Score: p=" + sidacCorrection(atopyVals) + "';");
            atopicAsthmaJS.append("document.getElementById('sidacPathwayScore').innerHTML ='Sidac Pathway Score: p=" + sidacCorrection(atopicAsthmaVals) + "';");
            ahrJS.append("document.getElementById('sidacPathwayScore').innerHTML ='Sidac Pathway Score: p=" + sidacCorrection(ahrVals) + "';");

            makePathwayForm.setNodeText(node.toString());
            makePathwayForm.setEdgeText(edge.toString());

            makePathwayForm.setAsthmaJS(asthmaJS.toString());
            makePathwayForm.setAtopyJS(atopyJS.toString());
            makePathwayForm.setAtopicAsthmaJS(atopicAsthmaJS.toString());
            makePathwayForm.setAhrJS(ahrJS.toString());

            forward = mapping.findForward("pathway");
        }
        return forward;
    }

    private String corrected(ArrayList<Double> vals)
    {
        double min = 1;
        for (Double d : vals)
        {
            if (d < min)
            {
                min = d;
            }
        }
        min = min * vals.size();
        if (min > 1)
        {
            min = 1;
        }
        return Double.toString(min);
    }

    private String sidacCorrection(ArrayList<Double> vals)
    {
        double tmp = 1;
        double min = 1;

        //find min value
        for (Double d : vals)
        {
            if (d < min)
            {
                min = d;
            }
        }

        //calcualte (1-min)^k
        tmp = (1 - min);
        for (int i = 1; i < vals.size(); i++)
        {
            tmp = tmp * (1 - min);
        }

        tmp = 1 - tmp;

        if (tmp > 1)
        {
            tmp = 1;
        }

        DecimalFormat formatter = new DecimalFormat("0.###E0");
        return formatter.format(tmp);
    }
}